package com.vpclub.config;

import com.vpclub.bean.Color;
import com.vpclub.bean.ColorFactoryBean;
import com.vpclub.bean.Person;
import com.vpclub.bean.Red;
import com.vpclub.condition.LinuxCondition;
import com.vpclub.condition.MyImportBeanDefinitionRegistrar2;
import com.vpclub.condition.MyImportSelector;
import com.vpclub.condition.WindowsCondition;
import org.springframework.context.annotation.*;

/**
 * @author : leimingchao
 * @Description:
 * @date Date : 2021年06月12日 21:40
 */

/**
 * 类中组件统一设置，满足当前条件，这个类中配置的所有bean注册才能生效
 */
@Conditional({WindowsCondition.class})
@Configuration
/**
 * @Import导入组件，id默认是组件的全类名
 */
// @Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
//MyImportSelector和MyImportBeanDefinitionRegistrar2不会注册到IOC容器中
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar2.class})
public class MainConfig2 {


    // 默认是单实例的
    @Bean(value = "person")
    /** @Scope：调整作用域
     * ConfigurableBeanFactory#SCOPE_PROTOTYPE:prototype
     * ConfigurableBeanFactory#SCOPE_SINGLETON:singleton
     * org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST:request
     * org.springframework.web.context.WebApplicationContext#SCOPE_SESSION:session
     *
     * prototype:多实例的，ioc容器启动并不会去调用方法创建对象放在容器中，
     *                     每次获取的时候才会调用方法创建对象
     * singleton：单实例，默认值，ioc容器启动会调用方法创建对象放到ioc容器中，
     *                           以后每次获取就是直接从ioc容器（map.get()）中拿
     * request:同一次请求创建一个实例
     * session：同一个session创建一个实例
     *
     *
     * 懒加载：
     *        单实例bean：默认在容器启动的时候创建对象
     *        懒加载：容器启动不创建对象，第一次使用（获取）Bean创建对象，并初始化
     *
     */
    //@Scope(value = "prototype")
    @Lazy
    public Person person() {
        System.out.println("给容器中添加Person........");
        return new Person("张三",25);
    }


    /**
     * @Conditional({Condition}):
     *      按照一定的条件进行判断，满足条件给容器中注册bean,SpringBoot底层使用到的注解
     *
     * 如果系统是windows,给容器中注册("bill")
     * 如果系统是Linux,给容器中注册("linus")
     */

    @Bean(value = "bill")
    public Person person01() {
        return new Person("Bill Gates",62);
    }

    @Conditional({LinuxCondition.class})
    @Bean(value = "linus")
    public Person person02() {
        return new Person("Linus",48);
    }

    /**
     * 给容器中注册组件
     * 1.包扫描+组件标注注解（@Controller/@Service/@Repository/@Component）[自己写的类]
     * 2.@Bean[导入的第三方包里面的组件]
     * 3.@Import[快速给容器中导入一个组件]
     *      1.@Import(要导入到容器中的组件)，容器中就会自动注册这个组件，id默认是全类名
     *      2.ImportSelector：返回需要导入的组件的全类名数组,实现ImportSelector接口的类不会注册到IOC容器中
     *      3.ImportBeanDefinitionRegistrar：手动注册bean到容器中，实现ImportBeanDefinitionRegistrar接口的类不会注册到IOC容器中
     * 4.使用Spring提供的FactoryBean(工厂Bean)
     *      1.默认获取到的是工厂bean调用getObject创建的对象
     *      2.获取工厂bean本身，我们需要给id前面加一个&
     *          &colorFactoryBean
     */

    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}
